package com.hhoss.snid;

import com.hhoss.logs.Logger;

import java.util.Arrays;

/**
 * return global unique 26W sequence in every second
 * will wait to next second if need more
 * @author kejun
 *
 */
public class KeyNum {	
	private static final Logger logger = Logger.get();
	
	private static final String SF18="%1$02d%2$02d%3$02d%4$02d%5$02d%6$02d%7$02d%8$04d";
	private static final String SF20="%1$04d%2$02d%3$02d%4$02d%5$02d%6$02d%7$02d%8$04d";
	private static final int code = SNID.appCode2();
    private static final int mask = 0x1FFF;;
	private static final int mini = 1<<10;
    private static long tims = SeqTims.val();
	private static int seq = 0;
	/**
	 * return a sequence, 8000 id per second, global unique.
	 * @return 18nums yyMMddHHmmss+code2+seq4 (170102123456991234)
	 * */
    public static String len18(){
    	int[] f= getFields();
    	return String.format(SF18,f[0],f[2],f[3],f[4],f[5],f[6],f[7],f[8]);
    }
	/**
	 * return a sequence, 8000 id per second, global unique.
	 * @return 18nums yyyyMMddHHmmss+code2+seq4 (20170102123456991234)
	 * */
    public static String len20(){
    	int[] f= getFields();
    	return String.format(SF20,f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8]);
    }
    
    private synchronized static int[] getFields(){
      	long now = SeqTims.val();
    	if(now<tims){
    		logger.error("system clock error, current[{}] is before old[{}]",now,tims);
    		throw new IllegalArgumentException("system clock error!");
    	}
      	seq = seq+1 & mask;
    	if(now>tims){
    		//logger.debug("tims:{}->{},seq:{}->0.",tims,now,seq);
     		seq=0;
    	}else if(seq==0){//wait to next time
     		logger.debug("cyclic too fast, wait to next second[{}].",tims);
    		while(SeqTims.val()<=tims)try{Thread.sleep(1);}catch(Exception e){}
      	}
    	tims=now;
    	//return Formatter.format(new Date(tims*1000),"yyMMddHHmmss")+code+(seq+mini);
    	int[] flds = Arrays.copyOf(SeqTims.meta(tims),9);
    	flds[7]=code;
    	flds[8]=seq+mini;
    	return flds;
    }

}
